# aem.two_d.single.head_line_sink -- Head-specified line-sinks
#
# Copyright (c) 2000, V.Kelson and M.Bakker

import line_sink

import geometry
XY = geometry.xy.XY

import aem.matrix

class HeadLineSink(line_sink.LineSink):
	'''Class for head-specified, constant strength linesinks

	Python call: LineSink(pt1,pt2,sigma,parent)

        Attributes:

          - pt1: first XY of line (from Line)
          - pt2: second XY of line (from Line)
          - width: width of line (from Line)
          - z1: complex coordinate of pt1 (from Line)
          - z2: complex coordinate of pt2 (from Line)
          - zc: complex coordinate of center of line (from Line)
          - zl: complex coordinate 0.5(z2-z1) (from Line)
          - halflength: half the length of the line (from Line)
          - parent: parent of the element (inherited from Element)
          - parameters: ColumnList of strength parameters, set to 0 (inherited from Element)
          - solver: solver (inherited from Element)
          - elementList: list of elements, defaults to itself (inherited from Element)
          - __numberOfParameters: number of parameters, set to 1 (inherited from LineSink)
          - factor: length/4pi (inherited from LineSink)
          - logzl: log(zl) (inherited from LineSink)
          - specifiedHead: head specified along element
          - overspec: number of control points (will be automatically generated according to cosine rule) 

        Overloaded methods from LineSink and Element:
        __init__, getMatrixCoefficients, getMatrixContribution, check
	'''
   
	def __init__(self,pt1=XY(-1.0,0.0),pt2=XY(1.0,0.0),specifiedHead=0.0,parent=None,overspec=1):
		'''Constructor'''
		# Call base class constructors
		line_sink.LineSink.__init__(self,pt1,pt2,0.0,parent)
		self.specifiedHead = specifiedHead
		self.givenElement = 0
		# Decode options for control-points
		self.controlPoints = self.computeControlPoints(overspec)

	def __repr__(self):
		# Parent not yet included
		return 'HeadLineSink' + str((self.pt1,self.pt2,self.specifiedHead))	

	def getMatrixCoefficients(self,fa,ctlPt):
		return fa(self,ctlPt)

	def getMatrixContribution(self,elementList):
		# Returns a tuple (mc,mr) where mc is a list of MatrixColumn objects
		# and mr is a list of MatrixRow objects
		rows = []
		columns = [aem.matrix.MatrixColumn(self,0)]
		for cp in self.controlPoints:
			mr = aem.matrix.MatrixRow()
			for e in elementList:
				mr.A = mr.A + e.getMatrixCoefficients(lambda z,p:z.potentialInfluence(p),cp)
				mr.b = self.headToPotential(cp,self.specifiedHead) - \
				                               self.potential(cp)
				rows.append(mr)
		return ( rows,columns )

	def check(self):
		# Checks the boundary condition(s)
		rv = []
		for cp in self.controlPoints:
			rv.append(self.head(cp) - self.specifiedHead)
		return rv
